<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:lcp="http://schemas.icitadel.com/Lazarus/CPP/Physical.xsd">

   <xsl:output method="text" />

   <xsl:include href="CPPIncludes.xslt" />

   <xsl:template match="lcp:Project">
      <xsl:apply-templates select="lcp:Classes/lcp:Class" />
   </xsl:template>

   <!-- ***** Class Template ***** -->
   <xsl:template match="lcp:Class">
      <xsl:variable name="RegionName" select="lcp:Names/lcp:Name[ @context = 'HeaderRegion' ]/@value" />
///////////////////////////////////////////////////////////
//  <xsl:value-of select="@filename" />
//  <xsl:value-of select="lcp:Description" />
//  Created on:      <xsl:value-of select="@created" />
//  Original author: <xsl:value-of select="@author" />
///////////////////////////////////////////////////////////

#pragma once

#ifndef <xsl:value-of select="$RegionName" />
#define <xsl:value-of select="$RegionName" />

#include "..\Common\dxstdafx.h"
<xsl:apply-templates select="lcp:Includes" />

namespace <xsl:value-of select="@namespace" />
<xsl:text>
{</xsl:text>
   <xsl:apply-templates select="lcp:Predeclares" />

   <xsl:text>
      
   public class </xsl:text>
      <xsl:value-of select="@name" />
      <xsl:text>
   {
</xsl:text>

      <xsl:call-template name="DeclareFriends">
         <xsl:with-param name="Source" select="lcp:Friends" />
      </xsl:call-template>
      <xsl:text>

   private:</xsl:text>
      <xsl:apply-templates select="lcp:Storage" />

      <xsl:call-template name="DeclareDefaultMethods">
         <xsl:with-param name="Source" select="lcp:Methods" />
         <xsl:with-param name="Scope">Private</xsl:with-param>
      </xsl:call-template>

      <xsl:text>

   protected:
      </xsl:text>
      <xsl:call-template name="DeclareDefaultMethods">
         <xsl:with-param name="Source" select="lcp:Methods" />
         <xsl:with-param name="Scope">Protected</xsl:with-param>
      </xsl:call-template>
      <xsl:call-template name="DeclareFireEvents">
         <xsl:with-param name="Source" select="lcp:Events" />
      </xsl:call-template>

      <xsl:text>
         
   public:
      </xsl:text>
      <xsl:call-template name="DeclareDefaultMethods">
         <xsl:with-param name="Source" select="lcp:Methods" />
         <xsl:with-param name="Scope">Public</xsl:with-param>
      </xsl:call-template>
      <xsl:apply-templates select="lcp:Methods/lcp:Method[ @type = 'Default' and @scope = 'Public' ]" />
      <xsl:apply-templates select="lcp:Properties" />
      <xsl:call-template name="DeclareAddEvents">
         <xsl:with-param name="Source" select="lcp:Events" />
      </xsl:call-template>
      <xsl:text>
   };
} 

#endif // </xsl:text>
      <xsl:value-of select="$RegionName" />
   </xsl:template>

   <!-- ***** Predeclare Template ***** -->
   <xsl:template match="lcp:Predeclares">
      <xsl:if test="count( lcp:Predeclare ) &gt; 0">
         <xsl:text>
</xsl:text>
         <xsl:apply-templates select="lcp:Predeclare" />
      </xsl:if>
   </xsl:template>

   <xsl:template match="lcp:Predeclare">
      <xsl:text>
   class </xsl:text>
      <xsl:value-of select="@class" />
      <xsl:text>;</xsl:text>
   </xsl:template>

   <!-- ***** Friends Template ***** -->
   <xsl:template name="DeclareFriends">
      <xsl:param name="Source" />
      <xsl:for-each select="$Source/lcp:Friend">
         <xsl:text>
      friend class </xsl:text>
         <xsl:value-of select="@class" />
         <xsl:text>;</xsl:text>
      </xsl:for-each>
   </xsl:template>
   
   <!-- ***** Storage Template ***** -->
   <xsl:template match="lcp:Storage">
      <xsl:if test="count( lcp:Field ) &gt; 0">
         <xsl:text>
</xsl:text>
         <xsl:apply-templates select="lcp:Field" />
      </xsl:if>
   </xsl:template>

   <xsl:template match="lcp:Field">
      <xsl:variable name="FieldType">
         <xsl:call-template name="Type.Get">
            <xsl:with-param name="Source" select="lcp:Type" />
            <xsl:with-param name="Context">CPP</xsl:with-param>
         </xsl:call-template>
      </xsl:variable>

      <xsl:text>
         </xsl:text>
      <xsl:value-of select="$FieldType" />
      <xsl:text> </xsl:text>
      <xsl:value-of select="@name" />
      <xsl:text>;</xsl:text>
   </xsl:template>

   <!-- ***** Property Template ***** -->
   <xsl:template match="lcp:Properties">
      <xsl:text>
         
		// ///////////////////////////////////////////////////////////////////////	//
		// Property Declarations																	//
		// ///////////////////////////////////////////////////////////////////////	//</xsl:text>
      <xsl:apply-templates select="lcp:Property" />
   </xsl:template>
   
   <xsl:template match="lcp:Property">
      <xsl:variable name="PropertyType">
         <xsl:call-template name="Type.Get">
            <xsl:with-param name="Source" select="lcp:Type" />
            <xsl:with-param name="Context">CPP</xsl:with-param>
         </xsl:call-template>
      </xsl:variable>
      <xsl:variable name="CurrentProperty" select="." />
      <xsl:variable name="Getter" select="./lcp:Property-Get" />
      <xsl:variable name="Setter" select="./lcp:Property-Set" />
      <xsl:variable name="GetMethod" select="ancestor::lcp:Class/lcp:Methods/lcp:Method[ @id = $Getter/@method ]" />
      <xsl:variable name="SetMethod" select="ancestor::lcp:Class/lcp:Methods/lcp:Method[ @id = $Setter/@method ]" />

      <xsl:text>
         
		// public property </xsl:text>
      <xsl:value-of select="$PropertyType" />
      <xsl:text> </xsl:text>
      <xsl:value-of select="@name" />
      <xsl:text> </xsl:text>
      <xsl:text>{ </xsl:text>
      <xsl:if test="$Getter">
         <xsl:text>get; </xsl:text>
      </xsl:if>
      <xsl:if test="$Setter">
         <xsl:text>set; </xsl:text>
      </xsl:if>
      <xsl:text>}</xsl:text>
      <xsl:call-template name="DeclareMethod">
         <xsl:with-param name="Source" select="$GetMethod" />
      </xsl:call-template>
      <xsl:call-template name="DeclareMethod">
         <xsl:with-param name="Source" select="$SetMethod" />
      </xsl:call-template>
   </xsl:template>

   <!-- ***** Method Template ***** -->
   <xsl:template name="DeclareDefaultMethods">
      <xsl:param name="Source" />
      <xsl:param name="Scope" />
      <xsl:for-each select="$Source/lcp:Method[ @type = 'Default' and @scope = $Scope ]">
         <xsl:call-template name="DeclareMethod">
            <xsl:with-param name="Source" select="." />
         </xsl:call-template>
      </xsl:for-each>
   </xsl:template>
   
   <xsl:template name="DeclareMethod">
      <xsl:param name="Source" />
      <xsl:if test="$Source">
      <xsl:text>
      </xsl:text>
      <xsl:if test="$Source/@virtual">virtual </xsl:if>
      <xsl:call-template name="Type.Get">
         <xsl:with-param name="Source" select="$Source/lcp:ReturnType" />
      </xsl:call-template>
      <xsl:text> </xsl:text>
      <xsl:value-of select="$Source/@name" />
      <xsl:call-template name="ParameterDeclaration">
         <xsl:with-param name="Source" select="$Source/lcp:Parameters" />
      </xsl:call-template>
      </xsl:if>
   </xsl:template>

   <xsl:template name="ParameterDeclaration">
      <xsl:param name="Source" />
      <xsl:variable name="ParameterCount" select="count( $Source/lcp:Parameter )" />
      <xsl:text>(</xsl:text>
      <xsl:if test="$ParameterCount &gt; 0">
         <xsl:text> </xsl:text>
         <xsl:for-each select="$Source/lcp:Parameter">
            <xsl:apply-templates select="." />
            <xsl:if test="position() &lt; $ParameterCount">
               <xsl:text>, </xsl:text>
            </xsl:if>
         </xsl:for-each>
         <xsl:text> </xsl:text>
      </xsl:if>
      <xsl:text>);</xsl:text>
   </xsl:template>

   <xsl:template match="lcp:Parameter">
      <xsl:call-template name="Type.Get">
         <xsl:with-param name="Source" select="lcp:Type" />
      </xsl:call-template>
      <xsl:text> </xsl:text>
      <xsl:value-of select="@name" />
   </xsl:template>

   <!-- ***** Event Template ***** -->
   <xsl:template name="DeclareFireEvents">
      <xsl:param name="Source" />
      <xsl:call-template name="DeclareFireEvent">
         <xsl:with-param name="Source" select="$Source/lcp:Event" />
      </xsl:call-template>
   </xsl:template>

   <xsl:template name="DeclareFireEvent">
      <xsl:param name="Source" />
      <xsl:variable name="EventType">
         <xsl:call-template name="Type.Get">
            <xsl:with-param name="Source" select="$Source/lcp:ArgumentType" />
         </xsl:call-template>
      </xsl:variable>
      <xsl:variable name="CurrentEvent" select="$Source" />
      <xsl:variable name="FireEvent" select="$Source/lcp:Event-Fire" />
      <xsl:variable name="FireMethod" select="$Source/ancestor::lcp:Class/lcp:Methods/lcp:Method[ @id = $FireEvent/@method ]" />

      <xsl:text>
         
		// public event </xsl:text>
      <xsl:value-of select="$EventType" />
      <xsl:text> </xsl:text>
      <xsl:value-of select="$Source/@name" />
      <xsl:call-template name="DeclareMethod">
         <xsl:with-param name="Source" select="$FireMethod" />
      </xsl:call-template>
   </xsl:template>


   <xsl:template name="DeclareAddEvents">
      <xsl:param name="Source" />
      <xsl:text>
         
		// ///////////////////////////////////////////////////////////////////////	//
		// Event Declarations																	//
		// ///////////////////////////////////////////////////////////////////////	//</xsl:text>
      <xsl:call-template name="DeclareAddEvent">
         <xsl:with-param name="Source" select="$Source/lcp:Event" />
      </xsl:call-template>
   </xsl:template>

   <xsl:template name="DeclareAddEvent">
      <xsl:param name="Source" />
      <xsl:variable name="EventType">
         <xsl:call-template name="Type.Get">
            <xsl:with-param name="Source" select="$Source/lcp:ArgumentType" />
         </xsl:call-template>
      </xsl:variable>
      <xsl:variable name="CurrentEvent" select="$Source" />
      <xsl:variable name="AddEvent" select="$Source/lcp:Event-Add" />
      <xsl:variable name="AddMethod" select="$Source/ancestor::lcp:Class/lcp:Methods/lcp:Method[ @id = $AddEvent/@method ]" />

      <xsl:text>
         
		// public event </xsl:text>
      <xsl:value-of select="$EventType" />
      <xsl:text> </xsl:text>
      <xsl:value-of select="$Source/@name" />
      <xsl:call-template name="DeclareMethod">
         <xsl:with-param name="Source" select="$AddMethod" />
      </xsl:call-template>
   </xsl:template>


   <!-- ***** Type Template ***** -->
   <xsl:template name="Type.Get">
      <xsl:param name="Source" />

      <xsl:choose>
         <xsl:when test="$Source">
            <xsl:value-of select="$Source/@name" />
            <xsl:variable name="TemplateParamCount" select="count( $Source/lcp:Template-Parameters/lcp:Template-Parameter )" />

            <xsl:if test="$Source/@is-template = 'True'">
               <xsl:text>&lt; </xsl:text>
               <xsl:for-each select="$Source/lcp:Template-Parameters/lcp:Template-Parameter">
                  <xsl:call-template name="Type.Get">
                     <xsl:with-param name="Source" select="./lcp:Type" />
                  </xsl:call-template>
                  <xsl:if test="position() &lt; $TemplateParamCount">
                     <xsl:text>, </xsl:text>
                  </xsl:if>
               </xsl:for-each>
               <xsl:text> &gt;</xsl:text>
            </xsl:if>
         </xsl:when>
      </xsl:choose>
   </xsl:template>


</xsl:stylesheet>